package com.dbw.englishassistant.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import com.dbw.englishassistant.service.MarkdownLineTool.MarkdownItem;
import com.dbw.englishassistant.service.MarkdownLineTool.MarkdownType;

public class MarkdownSentenceParser implements SentenceParser {

    private MarkdownItem currentMarkdownItem = null;
    
    private boolean isCurrentMarkdownItemHandled = false;
    
    private Sentence currentSentence = null;
    
    private List<Sentence> currentSentenceList = null;
    
    private ParseSate currentParseState = null;
    
    public MarkdownSentenceParser() {
    }
    

    @Override
    public List<Sentence> parse(String text) {
        
        currentSentenceList = new ArrayList<Sentence>();
        createSentence();
        currentParseState = ParseSate.MatchEnglishState;
        
        Scanner scanner = new Scanner(text);
        MarkdownLineTool markdownLineTool = new MarkdownLineTool();
        
        while(scanner.hasNext()) {
            String line = scanner.nextLine();
            currentMarkdownItem = markdownLineTool.parseLine(line);
            if(currentMarkdownItem.getLineType() == MarkdownType.TITLE) {
                break;
            }
            handleMarkdownItem();
        }
        scanner.close();
        
        commitSentence();
        
        return currentSentenceList;
    }
    
    private void handleMarkdownItem() {
        isCurrentMarkdownItemHandled = false;
        
        while(!isCurrentMarkdownItemHandled) {
            ParseSate nextState = currentParseState.parseLine(this);
            currentParseState = nextState;
        }
    }
    
    private void createSentence() {
        currentSentence = new Sentence();
    }
    
    private void commitSentence() {
        if(currentSentence.getEnglishSentence() == null) {
            return;
        }
        currentSentenceList.add(currentSentence);
        createSentence();
    }
    
    private void acceptMarkdownItem() {
        isCurrentMarkdownItemHandled = true;
    }

    private interface StepParser {
        public ParseSate parseLine(MarkdownSentenceParser sentenceParser);
    }
    
    private enum ParseSate implements StepParser {
        
        MatchEnglishState() {

            @Override
            public ParseSate parseLine(MarkdownSentenceParser sentenceParser) {

                MarkdownItem markdownItem = sentenceParser.currentMarkdownItem;
                String pureText = markdownItem.getPureText();
                
                if(markdownItem.getLineType() != MarkdownType.GENERAL_TEXT
                        || pureText.isEmpty()
                        || isChineseLine(pureText)) {
                    sentenceParser.acceptMarkdownItem();
                    return this;
                }
                
                sentenceParser.currentSentence.setEnglishSentence(pureText);
                sentenceParser.acceptMarkdownItem();
                return MatchChineseState;
            }
            
        },
        
        MatchChineseState() {

            @Override
            public ParseSate parseLine(MarkdownSentenceParser sentenceParser) {

                MarkdownItem markdownItem = sentenceParser.currentMarkdownItem;
                String pureText = markdownItem.getPureText();
                
                if(markdownItem.getLineType() != MarkdownType.GENERAL_TEXT
                        || pureText.isEmpty()
                        || !isChineseLine(pureText)) {
                    return HandleAbort;
                }
                
                sentenceParser.currentSentence.setChineseSentence(pureText);
                sentenceParser.acceptMarkdownItem();
                return MatchDetailState;
            }
            
        },
        
        MatchDetailState() {

            @Override
            public ParseSate parseLine(MarkdownSentenceParser sentenceParser) {

                MarkdownItem markdownItem = sentenceParser.currentMarkdownItem;
                String pureText = markdownItem.getPureText();
                
                if(markdownItem.getLineType() != MarkdownType.QUOTATION) {
                    return HandleAbort;
                }
                
                Sentence sentence = sentenceParser.currentSentence;
                sentence.setDetailDescription(
                        appendDetail(sentence.getDetailDescription(), pureText));
                sentenceParser.acceptMarkdownItem();
                
                return this;
            }
            
            private String appendDetail(String detail, String newDetail) {
                
                String lineSeparator = System.getProperty("line.separator");
                return detail != null ? detail + lineSeparator + newDetail
                        : newDetail;
            }
            
        },
        
        HandleAbort() {

            @Override
            public ParseSate parseLine(MarkdownSentenceParser sentenceParser) {
                sentenceParser.commitSentence();
                /* maybe the current markdown item is English sentence, so we can't accept it */
                return MatchEnglishState;
            }
            
        }
        
        ;

    }
    
    private static boolean isChineseLine(String line) {
        for(int i = 0; i < line.length(); i++) {
            char c = line.charAt(i);
            if(c > 256) {
                return true;
            }
        }
        
        return false;
    }
    
    
}
